home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Graphics / Ghostscript / source / gxfixed.h < prev    next >
C/C++ Source or Header  |  1997-06-17  |  9KB  |  228 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gxfixed.h */
  20. /* Fixed-point arithmetic for Ghostscript */
  21.  
  22. #ifndef gxfixed_INCLUDED
  23. #  define gxfixed_INCLUDED
  24.  
  25. /*
  26.  * Coordinates are generally represented internally by fixed-point
  27.  * quantities: integers lose accuracy in crucial places,
  28.  * and floating point arithmetic is slow.
  29.  */
  30. typedef long fixed;
  31. typedef ulong ufixed;        /* only used in a very few places */
  32. #define max_fixed max_long
  33. #define min_fixed min_long
  34. #define fixed_0 0L
  35. #define fixed_epsilon 1L
  36. /*
  37.  * 12 bits of fraction provides both the necessary accuracy and
  38.  * a sufficiently large range of coordinates.
  39.  */
  40. #define _fixed_shift 12
  41. #define fixed_fraction_bits _fixed_shift
  42. #define fixed_int_bits (sizeof(fixed) * 8 - _fixed_shift)
  43. #define fixed_scale (1<<_fixed_shift)
  44. #define _fixed_rshift(x) arith_rshift(x,_fixed_shift)
  45. #define _fixed_round_v (fixed_scale>>1)
  46. #define _fixed_fraction_v (fixed_scale-1)
  47. /*
  48.  * We use a center-of-pixel filling rule; Adobe specifies that coordinates
  49.  * designate half-open regions.  Because of this, we need special rounding
  50.  * to go from a coordinate to the pixel it falls in.  We use the term
  51.  * "pixel rounding" for this kind of rounding.
  52.  */
  53. #define _fixed_pixround_v (_fixed_round_v - fixed_epsilon)
  54.  
  55. /*
  56.  * Most operations can be done directly on fixed-point quantities:
  57.  * addition, subtraction, shifting, multiplication or division by
  58.  * (integer) constants; assignment, assignment with zero;
  59.  * comparison, comparison against zero.
  60.  * Multiplication and division by floats is OK if the result is
  61.  * explicitly cast back to fixed.
  62.  * Conversion to and from int and float types must be done explicitly.
  63.  * Note that if we are casting a fixed to a float in a context where
  64.  * only ratios and not actual values are involved, we don't need to take
  65.  * the scale factor into account: we can simply cast to float directly.
  66.  */
  67. #define int2fixed(i) ((fixed)(i)<<_fixed_shift)
  68. /* Define some useful constants. */
  69. /* Avoid casts, so strict ANSI compilers will accept them in #ifs. */
  70. #define fixed_1 (fixed_epsilon << _fixed_shift)
  71. #define fixed_half (fixed_1 >> 1)
  72. /*
  73.  * On 16-bit systems, we can convert fixed variables to ints more efficiently
  74.  * than general fixed quantities.  For this reason, we define two separate
  75.  * sets of conversion macros.
  76.  */
  77. #define fixed2int(x) ((int)_fixed_rshift(x))
  78. #define fixed2int_rounded(x) ((int)_fixed_rshift((x)+_fixed_round_v))
  79. #define fixed2int_ceiling(x) ((int)_fixed_rshift((x)+_fixed_fraction_v))
  80. #define fixed_pre_pixround(x) ((x)+_fixed_pixround_v)
  81. #define fixed2int_pixround(x) fixed2int(fixed_pre_pixround(x))
  82. #define fixed_is_int(x) !((x)&_fixed_fraction_v)
  83. #if arch_ints_are_short & !arch_is_big_endian
  84. /* Do some of the shifting and extraction ourselves. */
  85. #  define _fixed_hi(x) *((uint *)&(x)+1)
  86. #  define _fixed_lo(x) *((uint *)&(x))
  87. #  define fixed2int_var(x)\
  88.     ((int)((_fixed_hi(x) << (16-_fixed_shift)) +\
  89.            (_fixed_lo(x) >> _fixed_shift)))
  90. #  define fixed2int_var_rounded(x)\
  91.     ((int)((_fixed_hi(x) << (16-_fixed_shift)) +\
  92.            (((_fixed_lo(x) >> (_fixed_shift-1))+1)>>1)))
  93. #  define fixed2int_var_ceiling(x)\
  94.     (fixed2int_var(x) -\
  95.      arith_rshift((int)-(_fixed_lo(x) & _fixed_fraction_v), _fixed_shift))
  96. #else
  97. /* Use reasonable definitions. */
  98. #  define fixed2int_var(x) fixed2int(x)
  99. #  define fixed2int_var_rounded(x) fixed2int_rounded(x)
  100. #  define fixed2int_var_ceiling(x) fixed2int_ceiling(x)
  101. #endif
  102. #define fixed2int_var_pixround(x) fixed2int_pixround(x)
  103. #define fixed2long(x) ((long)_fixed_rshift(x))
  104. #define fixed2long_rounded(x) ((long)_fixed_rshift((x)+_fixed_round_v))
  105. #define fixed2long_ceiling(x) ((long)_fixed_rshift((x)+_fixed_fraction_v))
  106. #define fixed2long_pixround(x) ((long)_fixed_rshift((x)+_fixed_pixround_v))
  107. #define float2fixed(f) ((fixed)((f)*(float)fixed_scale))
  108. /* Note that fixed2float actually produces a double result. */
  109. #define fixed2float(x) ((x)*(1.0/fixed_scale))
  110.  
  111. /* Rounding and truncation on fixeds */
  112. #define fixed_floor(x) ((x)&(-1L<<_fixed_shift))
  113. #define fixed_rounded(x) (((x)+_fixed_round_v)&(-1L<<_fixed_shift))
  114. #define fixed_ceiling(x) (((x)+_fixed_fraction_v)&(-1L<<_fixed_shift))
  115. #define fixed_pixround(x) (((x)+_fixed_pixround_v)&(-1L<<_fixed_shift))
  116. #define fixed_fraction(x) ((int)(x)&_fixed_fraction_v)
  117. /* I don't see how to do truncation towards 0 so easily.... */
  118. #define fixed_truncated(x) ((x) < 0 ? fixed_ceiling(x) : fixed_floor(x))
  119.  
  120. #ifdef USE_FPU
  121. #  define USE_FPU_FIXED (USE_FPU < 0 && arch_floats_are_IEEE && arch_sizeof_long == 4)
  122. #else
  123. #  define USE_FPU_FIXED 0
  124. #endif
  125.  
  126. /*
  127.  * Define a procedure for computing a * b / c when b and c are non-negative,
  128.  * b < c, and a * b exceeds (or might exceed) the capacity of a long.
  129.  * It's really annoying that C doesn't provide any way to get at
  130.  * the double-length multiply/divide instructions that almost all hardware
  131.  * provides....
  132.  */
  133.  
  134. #if USE_FPU_FIXED
  135. fixed fixed_mult_quo(P3(fixed A, fixed B, fixed C));
  136. #else
  137. #  define fixed_mult_quo(fixed_a, fixed_b, fixed_c)\
  138.     ((fixed)floor((double)(fixed_a) * (fixed_b) / (fixed_c)))
  139. #endif
  140.  
  141. /*
  142.  * Transforming coordinates involves multiplying two floats, or a float
  143.  * and a double, and then converting the result to a fixed.  Since this
  144.  * operation is so common, we provide an alternative implementation of it
  145.  * on machines that use IEEE floating point representation but don't have
  146.  * floating point hardware.  The implementation may be in either C or
  147.  * assembler.
  148.  */
  149.  
  150. /*
  151.  * set_fmul2fixed_vars(R, FA, FB, dtemp) computes R = FA * FB:
  152.  *    R is a fixed, FA and FB are floats (not doubles), and
  153.  *      dtemp is a temporary double.
  154.  * set_dfmul2fixed_vars(R, DA, FB, dtemp) computes R = DA * FB:
  155.  *    R is a fixed, DA is a double, FB is a float, and
  156.  *      dtemp is a temporary double.
  157.  * R, FA, FB, and DA must be variables, not expressions.
  158.  */
  159. #if USE_FPU_FIXED && arch_sizeof_short == 2
  160. int set_fmul2fixed_(P3(fixed *, long, long));
  161. #define set_fmul2fixed_vars(vr,vfa,vfb,dtemp)\
  162.   set_fmul2fixed_(&vr, *(long *)&vfa, *(long *)&vfb)
  163. int set_dfmul2fixed_(P4(fixed *, ulong, long, long));
  164. #  if arch_is_big_endian
  165. #  define set_dfmul2fixed_vars(vr,vda,vfb,dtemp)\
  166.      set_dfmul2fixed_(&vr, ((ulong *)&vda)[1], *(long *)&vfb, *(long *)&vda)
  167. #  else
  168. #  define set_dfmul2fixed_vars(vr,vda,vfb,dtemp)\
  169.      set_dfmul2fixed_(&vr, *(ulong *)&vda, *(long *)&vfb, ((long *)&vda)[1])
  170. #  endif
  171. #else            /* don't bother */
  172. #  define set_fmul2fixed_vars(vr,vfa,vfb,dtemp)\
  173.      (dtemp = (vfa) * (vfb),\
  174.       (f_fits_in_bits(dtemp, fixed_int_bits) ? (vr = float2fixed(dtemp), 0) :\
  175.        gs_note_error(gs_error_limitcheck)))
  176. #  define set_dfmul2fixed_vars(vr,vda,vfb,dtemp)\
  177.      (dtemp = (vda) * (vfb),\
  178.       (f_fits_in_bits(dtemp, fixed_int_bits) ? (vr = float2fixed(dtemp), 0) :\
  179.        gs_note_error(gs_error_limitcheck)))
  180. #endif
  181. /*
  182.  * set_float2fixed_vars(R, F) does the equivalent of R = float2fixed(F):
  183.  *    R is a fixed, F is a float or a double.
  184.  * set_fixed2float_var(R, V) does the equivalent of R = fixed2float(V):
  185.  *    R is a float or a double, V is a fixed.
  186.  * set_ldexp_fixed2double(R, V, E) does the equivalent of R=ldexp((double)V,E):
  187.  *    R is a double, V is a fixed, E is an int.
  188.  * R and F must be variables, not expressions; V and E may be expressions.
  189.  */
  190. #if USE_FPU_FIXED
  191. int set_float2fixed_(P3(fixed *, long, int));
  192. int set_double2fixed_(P4(fixed *, ulong, long, int));
  193. # define set_float2fixed_vars(vr,vf)\
  194.     (sizeof(vf) == sizeof(float) ?\
  195.      set_float2fixed_(&vr, *(long *)&vf, fixed_fraction_bits) :\
  196.      set_double2fixed_(&vr, ((ulong *)&vf)[arch_is_big_endian],\
  197.                ((long *)&vf)[1 - arch_is_big_endian],\
  198.                fixed_fraction_bits))
  199. long fixed2float_(P2(fixed, int));
  200. void set_fixed2double_(P3(double *, fixed, int));
  201. # define set_fixed2float_var(vf,x)\
  202.     (sizeof(vf) == sizeof(float) ?\
  203.      (*(long *)&vf = fixed2float_(x, fixed_fraction_bits), 0) :\
  204.      (set_fixed2double_(&vf, x, fixed_fraction_bits), 0))
  205. #define set_ldexp_fixed2double(vd, x, exp)\
  206.   set_fixed2double_(&vd, x, -(exp))
  207. #else
  208. # define set_float2fixed_vars(vr,vf)\
  209.     (f_fits_in_bits(vf, fixed_int_bits) ? (vr = float2fixed(vf), 0) :\
  210.      gs_note_error(gs_error_limitcheck))
  211. # define set_fixed2float_var(vf,x)\
  212.     (vf = fixed2float(x), 0)
  213. # define set_ldexp_fixed2double(vd, x, exp)\
  214.     discard(vd = ldexp((double)(x), exp))
  215. #endif
  216.  
  217. /* A point with fixed coordinates */
  218. typedef struct gs_fixed_point_s {
  219.     fixed x, y;
  220. } gs_fixed_point;
  221.  
  222. /* A rectangle with fixed coordinates */
  223. typedef struct gs_fixed_rect_s {
  224.     gs_fixed_point p, q;
  225. } gs_fixed_rect;
  226.  
  227. #endif                    /* gxfixed_INCLUDED */
  228.